-module(binstring).

-compile(export_all).

len(Bins) when is_binary(Bins) ->
    byte_size(Bins).

chr(Bins, Char) when is_binary(Bins) ->
    chrc(Bins, Char, 0, byte_size(Bins)).

chrc(<<>>, Char, Offset, _Len) ->
    -1;
chrc(<<Char,_/binary>>, <<Char>>, Offset, _Len) ->
    Offset;
chrc(<<Byte,Rest/binary>>, <<Char>>, Offset, Remain) ->
    chrc(Rest, <<Char>>, Offset+1, Remain-1);
chrc(<<Char,_/binary>>, Char, Offset, _Len) ->
    Offset;
chrc(<<Byte,Rest/binary>>, Char, Offset, Remain) ->
    chrc(Rest, Char, Offset+1, Remain-1).

equal(BinString1, BinString2) ->     
    BinString1 =:= BinString2.

concat(BinString1, BinString2) ->
     list_to_binary([BinString1,BinString2]).

substr(BinString, Start) ->
    substr(BinString, Start, byte_size(BinString)).

substr(BinString, Start, Length) when Start>0 ->
    if 
	Length + Start -1 > byte_size(BinString) ->
	    Len = byte_size(BinString) - Start + 1;
	true ->
	    Len = Length
    end,
    Begin = Start-1,
    <<_:Begin/binary, Rest:Len/binary, _/binary>> = BinString,
    Rest.

find(BinString, SubString) ->
    {POSs,_} = tokens(BinString, SubString),
    POSs.

tokens(BinString, SubString) ->
    find(BinString, byte_size(BinString), SubString, byte_size(SubString), 1, [], [], []).

find(BinString, LenBin, SubString, LenSubString, Offset, Results, Token, Tokens) when LenBin >= LenSubString ->
    LenRest = LenSubString - 1,
    <<First:1/binary, Rest:LenRest/binary, Last/binary>> = BinString,
    EQ = equal(list_to_binary([First,Rest]), SubString),
    case EQ of
	true ->
	    find(Last, byte_size(Last), SubString, LenSubString, 
		 Offset+LenSubString, [Offset|Results],
		 [], [list_to_binary(lists:reverse(Token))|Tokens]);
	_ ->
	    RestString = list_to_binary([Rest,Last]),
	    find(RestString, byte_size(RestString), SubString, LenSubString, 
		 Offset+1, Results,
		 [First|Token],Tokens)
    end;
find(BinString, _LenBin, _SubString, _LenSubString, _Offset, Results, Token, Tokens) ->
    {lists:reverse(Results),lists:reverse([list_to_binary( lists:reverse([BinString|Token]))|Tokens]) }.

urlparse(UrlString) ->   
    {_,Segs} = tokens(UrlString,<<"&">>),
    UrlDict = lists:foldl(fun(Seg,Dict) -> 
				  {_,[K,V]} = tokens(Seg,<<"=">>),
				  dict:store(K,V,Dict)
			  end, dict:new(), Segs).
    
refoffset(Seps) ->
    Nseps = lists:map(fun(N) -> {N,N} end, Seps),
    refoffset(Nseps,[]).

refoffset([{F,Fn},{S,Sn}|Rest],Ref) ->
    Sn1 = S-F+1,
    refoffset([{S,Sn1}|Rest],[Fn|Ref]);
refoffset([{F,Fn}], Ref) ->
    lists:reverse([Fn|Ref]).

tokens0(BinString, SepString) ->
    Seps = find(BinString, SepString),
    Rseps = refoffset(Seps),
    lists:foldl(fun(Pos, Acc) ->
			[{data,Bins},{list,Tokens}] = Acc,
			NPos = Pos-1,
			<<Token:NPos/binary,Rest/binary>> = Bins,
			[{data,Rest},{list,[Token|Tokens]}]
		end,[{data,BinString},{list,[]}],Rseps).
    

